package com.suxin.logger;

import com.suxin.logger.filter.Filter;
import com.suxin.logger.handler.Handler;
import sun.reflect.Reflection;

import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author Tang
 * @classname Logger
 * @description [ 日志记录器 ]
 * @date 2022/4/26 22:09
 */
public class Logger {

    private static final Handler emptyHandlers[] = new Handler[0];
    private static final CopyOnWriteArrayList<Handler> handles = new CopyOnWriteArrayList<>();

    private volatile LogManager logManager;

    private final Class<?> caller;
    private final String name;

    private volatile Level level;
    private volatile int levelValue;

    private Filter filter;

    public Logger(String name, Class<?> caller,Level level) {
        this.name = name;
        this.caller = caller;
    }

    public Logger(String name, Class<?> caller) {
        this(name, caller, Level.INFO);
    }

    public void info(String msg) {
        log(Level.INFO, msg);
    }

    public void warning(String msg) {
        log(Level.WARNING, msg);
    }

    private void log(Level level, String msg) {
        if (isLoggable(level)) {
            return;
        }
        LogRecord lr = new LogRecord(level,msg);
        doLog(lr);
    }

    private void doLog(LogRecord lr) {
        lr.setLoggerName(this.name);
        log(lr);
    }

    public void log(LogRecord lr) {
        if (isLoggable(level)) {
            return;
        }
        Filter thenFilter = this.filter;
        if (thenFilter != null && !thenFilter.isLoggable(lr)) {
            return;
        }
        Handler[] handles = this.getHandles();
        for (Handler handle : handles) {
            handle.publish(lr);
        }
    }

    public Handler[] getHandles() {
        return handles.toArray(emptyHandlers);
    }

    private boolean isLoggable(Level level) {
        return level.getValue() > this.levelValue || level.getValue() == this.levelValue;
    }

    public static Logger getLogger(String name) {
        return demandLogger(name, Reflection.getCallerClass(1));
    }

    private static Logger demandLogger(String name,Class<?> caller) {
        LogManager logManager = LogManager.getLogManager();
        return logManager.demandLogger(name,caller);
    }

    private void addHandle(Handler handler) {
        handles.add(handler);
    }

    public String getName() {
        return name;
    }

    public Level getLevel() {
        return level;
    }

    public void setLevel(Level level) {
        this.level = level;
        this.levelValue = level.getValue();
    }
}